parser grammar ValParser;

options {
  output = AST;
  tokenVocab = ValLexer;
}

tokens {
  EXPR;
  VARIABLES;
  VARIABLE;
  NAME;
  VALUE;
  FUNCTION;
  PARAM;
}

@header{
  package org.concepts.java.antlr.validator;
}

/*
 * Sample validation queries:
 *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 * name = foo;
 * first = 35;
 * second = 20;
 *
 * (length($first) + 2) > 3 && $second < (15 * 2) && matches($name, foo)
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 * first = 35;
 * second = 20 + $first;
 * third = $second - $first;
 * 
 * $second > 25 && $third == 20
 * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 *
 */


/*
 * Validator consists of zero or more variable declarations followed by
 * an expression that's evaluated.
 */
validator: variableDeclaration* expr?
	-> ^(VARIABLES variableDeclaration*) ^(EXPR expr)
	;

/*
 * Variable name should start with an alphanumeric and after
 * that it can contain alphanumeric or special character.
 */
variableName  : ALPHANUMERIC (ALPHANUMERIC | SPECIALCHARACTERS)* ;

variableDeclaration
  :  variableName  EQUAL  expr  QUOTE
  -> ^(VARIABLE ^(NAME variableName)  ^(VALUE expr))
    ;

/*
 * Variable reference. E.g. $name
 */
variableReference
  : DOLLAR variableName
  -> ^(DOLLAR variableName)
  ;


/*
 * Functional call. E.g. matches($name, abc)
 */
function
  : ALPHANUMERIC LPAREN expr? (COMMA expr)* RPAREN
  -> ^(FUNCTION ^(NAME ALPHANUMERIC) ^(PARAM expr* ) )
  ;
  
  
/*
 * Operator precedence
 * 
 *   '*', '/'
 *   '+', '-'
 *   '>', '<', '>=', '<='
 *   '==' '!='
 *   '&&'
 *   '||'
 *
 */  
  
expr  : andexpr  (OR^ andexpr )*;

andexpr       : equalityexpr (AND^ equalityexpr)*;

equalityexpr  : relationalexpr ( (EQ^ | NEQ^) relationalexpr)*;

relationalexpr: plusminusexpr ( ( GT^ | LT^ | GTE^ | LTE^ ) plusminusexpr)*;  
  
plusminusexpr : multdivideexpr ( (PLUS^ | MINUS^) multdivideexpr)*;

multdivideexpr: atom ( (MULTIPLY^ | DIVIDE^) atom )*;

atom 
	:
	function
	|
	variableReference
	|
	STRING 
	| 
	ALPHANUMERIC 
	| 
	SPECIALCHARACTERS	
	|    
	LPAREN expr RPAREN -> expr
	;





